#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <semaphore.h>
using namespace std;

const int gcap = 10;
template <class T>
class Ringqueue{
public:
    Ringqueue():ringqueue_(gcap),pIndex_(0),cIndex_(0)
    {
        pthread_mutex_init(&pmutex_,nullptr);
        pthread_mutex_init(&cmutex_,nullptr);
        sem_init(&roomsem_,0,ringqueue_.size());
        sem_init(&datasem_,0,0);
    }
    ~Ringqueue(){
        pthread_mutex_destroy(&pmutex_);
        pthread_mutex_destroy(&cmutex_);
        sem_destroy(&roomsem_);
        sem_destroy(&datasem_);
    }
    void push(const T& t){  //生产
        sem_wait(&roomsem_);
        pthread_mutex_lock(&pmutex_);
        ringqueue_[pIndex_]=t;
        pIndex_++;
        pIndex_%=ringqueue_.size();
        pthread_mutex_unlock(&pmutex_);
        sem_post(&datasem_);
    }
    T pop(){
        sem_wait(&datasem_);
        pthread_mutex_lock(&cmutex_);
        T tmp=ringqueue_[cIndex_];
        cIndex_++;
        cIndex_%=ringqueue_.size();
        pthread_mutex_unlock(&cmutex_);
        sem_post(&roomsem_);
        return tmp;
    }
private:
    vector<T> ringqueue_;	//阻塞队列
    uint32_t pIndex_;     // 当前生产者写入的位置， 如果是多线程，pIndex_也是临界资源
    uint32_t cIndex_;     // 当前消费者读取的位置，如果是多线程，cIndex_也是临界资源
    pthread_mutex_t pmutex_;	
    pthread_mutex_t cmutex_;
    sem_t roomsem_;
    sem_t datasem_;
};